<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */

namespace App\Websocket;

use Hyperf\Context\ApplicationContext;
use Hyperf\Contract\OnCloseInterface;
use Hyperf\Contract\OnMessageInterface;
use Hyperf\Contract\OnOpenInterface;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Engine\WebSocket\Frame;
use Hyperf\Engine\WebSocket\Response;
use Hyperf\Logger\LoggerFactory;
use Hyperf\Redis\Redis;
use Hyperf\WebSocketServer\Constant\Opcode;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use RedisException;

class ScoreWebsocket implements OnMessageInterface, OnOpenInterface, OnCloseInterface
{
    public const string KEY_FDS = 'fds:match';

    #[Inject]
    protected ContainerInterface $container;

    public function onMessage($server, $frame): void
    {
        $response = (new Response($server))->init($frame);
        if ($frame->opcode == Opcode::PING) {
            $response->push(new Frame(opcode: Opcode::PONG));
            return;
        }
        $response->push(new Frame(payloadData: 'Recv: ' . $frame->data));
    }

    public function onClose($server, int $fd, int $reactorId): void
    {
        try {
            $redis = ApplicationContext::getContainer()->get(Redis::class);
            $redis->sRem(self::KEY_FDS, $fd);
        } catch (ContainerExceptionInterface|NotFoundExceptionInterface|RedisException $e) {
            echo $e->getMessage();
        }
    }

    public function onOpen($server, $request): void
    {
        try {
            $redis = ApplicationContext::getContainer()->get(Redis::class);
            $redis->sAdd(self::KEY_FDS, $request->fd);
        } catch (ContainerExceptionInterface|NotFoundExceptionInterface|RedisException $e) {
            echo $e->getMessage();
        }
        $response = (new Response($server))->init($request);
        $response->push(new Frame(payloadData: 'Opened'));
    }
}
